from django.shortcuts import render, redirect, reverse
from utils.LoginRequremixIn import LoginRequireMixIn
from django.views import View
from goods.models import Goods
from django_redis import get_redis_connection
from order.models import AreaInfo
from django.http import JsonResponse
from user.models import User, Address
import re
from datetime import datetime
from order.models import OrderInfo, OrderGoods
from django.db import transaction
from alipay import AliPay
from django.conf import settings
import os
from utils.LoginRequremixIn import LoginRequireMixIn


# mysql 事务知识点
# savepoint 事务名
# begin 开启事务
# commit 提交事务
# rollback 回滚
# rollback to 事务名 回滚到本事务名的位置


class Order(LoginRequireMixIn, View):
    # def get(self, request):
    #     user = request.user
    #
    #     user_address = Address.object.get_dafult_add(user)
    #
    #     if user_address == None:
    #         user_address = ''
    #
    #     return render(request, 'order.html', {'address': user_address})

    def post(self, request):

        user = request.user
        address = Address.object.get_dafult_add(user)
        goodses = request.POST.getlist('goods_id')
        goods_str = ','.join(goodses)
        conn = get_redis_connection('default')
        cart_key = "cart_%d" % user.id
        cart_count = conn.hlen(cart_key)
        if not goodses:
            return redirect(reverse('cart:carts'))
        goodlist = []
        total_price = 0
        total_count = 0
        for goods in goodses:
            good = Goods.objects.get(id=goods)
            count = conn.hget(cart_key, goods)
            amount = int(count) * good.price
            good.count = int(count)
            good.amount = float(amount)
            total_count += int(count)
            total_price += amount

            goodlist.append(good)

        context = {
            'count': total_count,
            'amount': total_price,
            'goodlist': goodlist,
            'goods_str': goods_str,
            'address': address,
            'cart_count': cart_count
        }

        return render(request, 'order.html', context)


def area(request):
    list = AreaInfo.objects.filter(aParent__isnull=True)
    list2 = []
    for item in list:
        list2.append([item.id, item.atitle])
    return JsonResponse({'data': list2})


def area2(request, pid):
    list = AreaInfo.objects.filter(aParent=pid)
    list2 = []
    for item in list:
        list2.append([item.id, item.atitle])
    return JsonResponse({'data': list2})


# 这是悲观锁的写法
class Commit1(View):

    @transaction.atomic
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '该用户未登陆'})
        reciver_addr = request.POST.get('reciver_addr')
        reciver = request.POST.get('reciver')
        tel = request.POST.get('tel')
        email = request.POST.get('email', user.email)
        remeber = request.POST.get('remember')
        goods_ids = request.POST.get('goods_str')
        if not all([reciver_addr, reciver, tel]):
            return JsonResponse({'res': 1, 'errmsg': '数据不完整'})

        # 校验邮箱
        if email != '':
            if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return JsonResponse({'res': 2, 'errmsg': '邮箱格式错误'})
        if not re.match(r'^1[35678]\d{9}$', tel):
            return JsonResponse({'res': 2, 'errmsg': '电话格式错误'})

        address = Address.object.get_dafult_add(user)

        if address is None:
            Address.objects.create(
                user=user,
                reciver=reciver,
                addr=reciver_addr,
                mail=email,
                tel=tel
            )
            address = Address(user=user)
        if remeber == 'true':
            address.tel = tel
            address.reciver = reciver
            address.addr = reciver_addr
            address.mail = email
            address.save()

        # todo: 创建核心业务
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
        total_count = 0
        total_price = 0
        conn = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id

        s_id = transaction.savepoint()
        try:
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                addr=address,
                total_price=total_price,
                total_count=total_count,
            )
            goods_ids = goods_ids.split(',')
            for goods_id in goods_ids:
                import time
                time.sleep(10)
                try:
                    goods = Goods.objects.select_for_update().get(id=goods_id)
                    # 悲观锁写法
                    # goods = Goods.objects.select_for_update().get(id=goods_id)
                    print('user:%s stock:%d' % (user.username, goods.stock))
                    # goods = Goods.objects.get(id=goods_id)
                except Goods.DoesNotExist:
                    # 不要写错
                    transaction.savepoint_rollback(s_id)
                    return JsonResponse({'res': 3, 'errmsg': '商品不存在'})

                count = conn.hget(cart_key, goods_id)

                if int(count) > goods.stock:
                    transaction.savepoint_rollback(s_id)
                    return JsonResponse({'res': 5, 'errmsg': '库存不足'})

                OrderGoods.objects.create(
                    order=order,
                    goodes=goods,
                    count=count,
                    price=goods.price,

                )

                goods.stock -= int(count)
                goods.save()

                amount = goods.price * int(count)
                total_count += int(count)
                total_price += amount
            # 更新购物车
            conn.hdel(cart_key, *goods_ids)

            order.total_price = total_price
            order.total_count = total_count
            order.save()
        except:
            transaction.savepoint_rollback(s_id)
            return JsonResponse({'err': 7, 'errmsg': '创建失败'})

        transaction.savepoint_commit(s_id)

        return JsonResponse({'res': 4, 'errmsg': '创建成功'})


# 这是乐观锁的写法
class Commit(View):

    @transaction.atomic
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '该用户未登陆'})
        reciver_addr = request.POST.get('reciver_addr')
        reciver = request.POST.get('reciver')
        tel = request.POST.get('tel')
        email = request.POST.get('email', user.email)
        remeber = request.POST.get('remember')
        goods_ids = request.POST.get('goods_str')
        if not all([reciver_addr, reciver, tel]):
            return JsonResponse({'res': 1, 'errmsg': '数据不完整'})

        # 校验邮箱
        if email != '':
            if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return JsonResponse({'res': 2, 'errmsg': '邮箱格式错误'})
        if not re.match(r'^1[35678]\d{9}$', tel):
            return JsonResponse({'res': 2, 'errmsg': '电话格式错误'})

        address = Address.object.get_dafult_add(user)

        if address is None:
            Address.objects.create(
                user=user,
                reciver=reciver,
                addr=reciver_addr,
                mail=email,
                tel=tel
            )
            address = Address(user=user)
        if remeber == 'true':
            address.tel = tel
            address.reciver = reciver
            address.addr = reciver_addr
            address.mail = email
            address.save()

        # todo: 创建核心业务
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id)
        total_count = 0
        total_price = 0
        conn = get_redis_connection('default')
        cart_key = 'cart_%d' % user.id

        s_id = transaction.savepoint()
        try:
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                addr=address,
                total_price=total_price,
                total_count=total_count,
            )
            goods_ids = goods_ids.split(',')
            for goods_id in goods_ids:
                for i in range(3):
                    try:
                        goods = Goods.objects.select_for_update().get(id=goods_id)
                    except Goods.DoesNotExist:
                        transaction.savepoint_rollback(s_id)
                        return JsonResponse({'res': 3, 'errmsg': '商品不存在'})

                    count = conn.hget(cart_key, goods_id)

                    if int(count) > goods.stock:
                        transaction.savepoint_rollback(s_id)
                        return JsonResponse({'res': 5, 'errmsg': '库存不足'})
                    orige_stock = goods.stock
                    new_stock = goods.stock - int(count)

                    # 返回受影响的行数
                    rows = Goods.objects.filter(id=goods.id, stock=orige_stock).update(stock=new_stock)
                    if rows == 0:
                        if i == 2:
                            transaction.savepoint_rollback(s_id)
                            return JsonResponse({'res': 7, 'errmsg': '下单失败2'})

                    OrderGoods.objects.create(
                        order=order,
                        goodes=goods,
                        count=count,
                        price=goods.price,

                    )

                    amount = goods.price * int(count)
                    total_count += int(count)
                    total_price += amount
                    break
                # 更新购物车

                order.total_price = total_price
                order.total_count = total_count
                order.save()
        except Exception as e:
            transaction.savepoint_rollback(s_id)
            return JsonResponse({'err': 7, 'errmsg': '创建失败'})
        conn.hdel(cart_key, *goods_ids)

        transaction.savepoint_commit(s_id)

        return JsonResponse({'res': 4, 'errmsg': '创建成功'})


class OrderPay(View):
    def post(self, request):
        order_id = request.POST.get('order_id')
        user = request.user
        if not user.is_authenticated:
            return JsonResponse({'res': 0, 'errmsg': '用户未登陆'})


        if not order_id:
            return JsonResponse({'res': 1, 'errmsg': '订单编号无效'})
        try:
            order = OrderInfo.objects.get(user=user,
                                          order_id=order_id,
                                          order_status=1)
        except order.DoesNotExist:
            return JsonResponse({'res': 2, 'errmsg': '订单不存在'})

        app_private_key_string = open(os.path.join(settings.BASE_DIR, 'order/app_private_key.pem')).read()
        alipay_public_key_string = open(os.path.join(settings.BASE_DIR, 'order/alipay.pem')).read()

        # print(os.path.join(settings.BASE_DIR, 'order/app_private_key.pem'))
        alipay = AliPay(
            appid="2016101700710647",
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key_string,
            # 支付宝的公钥，验证支付宝回传消息使用，不是你自己的公钥,
            alipay_public_key_string=alipay_public_key_string,
            sign_type="RSA2",  # RSA 或者 RSA2
            debug=True  # 默认False
        )
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order.order_id,
            total_amount=str(order.total_price),
            subject='computer saler%s'%order_id,
            return_url="https://127.0.0.0/computer",
            notify_url="https://example.com/notify"  # 可选, 不填则使用默认notify url
        )
        pay_url = 'https://openapi.alipaydev.com/gateway.do?' + order_string
        return JsonResponse({'res': 3, 'payurl':pay_url})


def check_pay(request):
    order_id = request.POST.get('order_id')
    user = request.user
    if not user.is_authenticated:
        return JsonResponse({'res': 0, 'errmsg': '用户未登陆'})

    if not order_id:
        return JsonResponse({'res': 1, 'errmsg': '订单编号无效'})
    try:
        order = OrderInfo.objects.get(user=user,
                                      order_id=order_id,
                                      order_status=1)
    except order.DoesNotExist:
        return JsonResponse({'res': 2, 'errmsg': '订单不存在'})

    app_private_key_string = open(os.path.join(settings.BASE_DIR, 'order/app_private_key.pem')).read()
    alipay_public_key_string = open(os.path.join(settings.BASE_DIR, 'order/alipay.pem')).read()
    alipay = AliPay(
        appid="2016101700710647",
        app_notify_url=None,  # 默认回调url
        app_private_key_string=app_private_key_string,
        alipay_public_key_string=alipay_public_key_string,
        sign_type="RSA2",  # RSA 或者 RSA2
        debug=True  # 默认False
    )

    """
    def api_alipay_trade_query(self, out_trade_no=None, trade_no=None):
       
        response = {
          "alipay_trade_query_response": {
            "trade_no": "2017032121001004070200176844",
            "code": "10000",
            "invoice_amount": "20.00",
            "open_id": "20880072506750308812798160715407",
            "fund_bill_list": [
              {
                "amount": "20.00",
                "fund_channel": "ALIPAYACCOUNT"
              }
            ],
            "buyer_logon_id": "csq***@sandbox.com",
            "send_pay_date": "2017-03-21 13:29:17",
            "receipt_amount": "20.00",
            "out_trade_no": "out_trade_no15",
            "buyer_pay_amount": "20.00",
            "buyer_user_id": "2088102169481075",
            "msg": "Success",
            "point_amount": "0.00",
            "trade_status": "TRADE_SUCCESS",
            "total_amount": "20.00"
          },
          "sign": ""
        }
        """
    while True:

        result = alipay.api_alipay_trade_query(order_id)

        # 获取错误码
        code = result.get('code')
        print(code)
        # 获取订单状态
        trade_status = result.get('trade_status')
        print(trade_status)
        # 支付成功
        if code == '10000' and trade_status == "TRADE_SUCCESS":
            order.trade_no = result.get('trade_no')
            order.order_status = 4
            order.save()
            return JsonResponse({'res': 3, 'errmsg': '支付完成'})
        elif code == '40004' or (code == '10000' and trade_status == "WAIT_BUYER_PAY"):
            # 等待买家付款
            import time
            time.sleep(5)
            continue
        else:
            return JsonResponse({'res':5, 'errmsg': '交易失败'})


class Comment(LoginRequireMixIn ,View):
    def get(self, request, order_id):
        try:
            order = OrderInfo.objects.get(order_id=order_id)
        except:
            return redirect(reverse('user:user_info'))
        order_goods = order.ordergoods_set.all()
        context = {'order_goods': order_goods, 'order_id': order_id}
        return render(request, 'comment.html', context)


class Commentpost(View):
    def post(self, request):
        user = request.user
        if not user.is_authenticated:
            return(reverse('user:user_info'))

        order_id = request.POST.get('order_id')
        count = request.POST.get('total')
        count = int(count)

        try:
            order = OrderInfo.objects.get(order_id=order_id, user=user)
        except order.DoesNotExist:
            return(reverse('user:user_info'))

        for i in range(1, count + 1):
            goods_id = request.POST.get('goods%s'%i)
            comment = request.POST.get('comment%s'%i)
            try:
                order_goods = OrderGoods.objects.get(order=order, goodes=goods_id)
            except:
                continue
            order_goods.comment = comment
            order_goods.save()
        order.order_status = 5
        order.save()


        return redirect(reverse('user:user_info'))



